from .base import ImageProcessor
from PIL import Image
from ui import ImageProcessorUI

class CropProcessor(ImageProcessor):
    def process(self, image: Image.Image, **kwargs) -> Image.Image:
        """
        裁剪图像。
        参数:
        - image: Image.Image - 输入的图像对象，类型为Pillow库中的Image.Image。
        - **kwargs: 关键字参数，必须包含 'left', 'upper', 'right', 'lower'。
        返回:
        - Image.Image - 裁剪后的图像对象，类型为Pillow库中的Image.Image。
        异常:
        - ValueError: 如果未提供完整的裁剪参数或参数无效。
        """
        left = kwargs.get('left')
        upper = kwargs.get('upper')
        right = kwargs.get('right')
        lower = kwargs.get('lower')
        if None in (left, upper, right, lower):
            raise ValueError("必须提供完整的裁剪参数：left, upper, right, lower")
        if not all(isinstance(val, int) for val in (left, upper, right, lower)):
            raise ValueError("所有裁剪参数必须是整数")
        width, height = image.size
        if not (0 <= left < right <= width and 0 <= upper < lower <= height):
            raise ValueError(f"裁剪区域无效。需满足：0 ≤ left < right ≤ {width} 且 0 ≤ upper < lower ≤ {height}")
        return image.crop((left, upper, right, lower))

    def get_ui_parameters(self, ui: "ImageProcessorUI") -> dict:
        if not hasattr(ui, 'crop_rect') or ui.crop_rect is None:
            ui.show_error("请先在图像上选择裁剪区域")
            return {}
        left, upper, right, lower = ui.crop_rect
        original_img = ui.app.current_image
        preview_img = ui.preview_image
        if original_img is None or preview_img is None:
            raise ValueError("当前没有可用图像")
        # 获取图像在label中的实际显示位置
        label_width = ui.image_label.winfo_width()
        label_height = ui.image_label.winfo_height()
        img_width, img_height = preview_img.size
        # 计算图像在label中的偏移（居中情况）
        offset_x = (label_width - img_width) // 2
        offset_y = (label_height - img_height) // 2
        # 调整裁剪坐标（减去偏移量）
        left = max(0, left - offset_x)
        upper = max(0, upper - offset_y)
        right = min(img_width, right - offset_x)
        lower = min(img_height, lower - offset_y)
        # 计算缩放比例
        scale_x = original_img.width / img_width
        scale_y = original_img.height / img_height
        return {
            "left": int(left * scale_x),
            "upper": int(upper * scale_y),
            "right": int(right * scale_x),
            "lower": int(lower * scale_y)
        }